#include "AESettingsManager.hpp"

#include <Shlwapi.h>
#include <iostream>

#include "AELogManager.hpp"

template<> arete::io::AESettingsManager* Ogre::Singleton<arete::io::AESettingsManager>::msSingleton = 0;

using namespace arete::io;

BEGIN_ARETE_NAMESPACE(io)

	AESettingsManager::AESettingsManager(void)
{
}

AESettingsManager::~AESettingsManager(void)
{
	m_config_options.clear();
}

void AESettingsManager::initialize(const string &_dir, const string &_fileName)
{
	AELogManager::log(ELL_NONE,"*****************************************");
	AELogManager::log(ELL_NONE,"*** ---   Loading settings.cfg    --- ***");
	AELogManager::log(ELL_NONE,"*****************************************");

	m_config_file = _dir + _fileName;

	m_config_options["Application"] = Ogre::NameValuePairList();
	m_config_options["Application"]["UserDir"] = _dir;
	m_config_options["Application"]["LogLevel"] = std::to_string(Ogre::LL_LOW);

	SYSTEM_INFO info;
	GetSystemInfo(&info);
	int cores = info.dwNumberOfProcessors;
	m_config_options["Application"]["Cores"] = std::to_string(cores);
}

void AESettingsManager::loadSettings(void)
{
	Ogre::ConfigFile file;
	file.loadDirect(m_config_file);

	string sec,key,value;

	Ogre::ConfigFile::SectionIterator seci = file.getSectionIterator();
	while(seci.hasMoreElements())
	{
		sec = seci.peekNextKey();

		m_config_options[sec] = Ogre::NameValuePairList();

		Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;
		for(i = settings->begin(); i != settings->end(); ++i)
		{
			key = i->first;
			value = i->second;

			m_config_options[sec][key] = value;
		}

		seci.moveNext();
	}
}

string AESettingsManager::getSettingAsString(const string &_section, const string &_name, const string &_default)
{
	if(m_config_options.find(_section) == m_config_options.end())
	{
		return _default;
	}
	else if(m_config_options[_section].find(_name) == m_config_options[_section].end())
	{
		return _default;
	}
	else
	{
		return m_config_options[_section][_name];
	}
}

int AESettingsManager::getSettingAsInt(const string &_section, const string &_name, int _default)
{
	if(m_config_options.find(_section) == m_config_options.end())
	{
		return _default;
	}
	else if(m_config_options[_section].find(_name) == m_config_options[_section].end())
	{
		return _default;
	}
	else
	{
		return atoi(m_config_options[_section][_name].c_str());
	}
}

float AESettingsManager::getSettingAsFloat(const string &_section, const string &_name, float _default)
{
	if(m_config_options.find(_section) == m_config_options.end())
	{
		return _default;
	}
	else if(m_config_options[_section].find(_name) == m_config_options[_section].end())
	{
		return _default;
	}
	else
	{
		return atof(m_config_options[_section][_name].c_str());
	}
}

bool AESettingsManager::getSettingAsBool(const string &_section, const string &_name, bool _default)
{
	if(m_config_options.find(_section) == m_config_options.end())
	{
		return _default;
	}
	else if(m_config_options[_section].find(_name) == m_config_options[_section].end())
	{
		return _default;
	}
	else
	{
		return m_config_options[_section][_name] == "true";
	}
}

void AESettingsManager::setSetting(const string &_section, const string &_name, const string &_value)
{
	if(m_config_options.find(_section) != m_config_options.end())
	{
		m_config_options[_section][_name] = _value;
	}
	else
	{
		m_config_options[_section] = Ogre::NameValuePairList();
		m_config_options[_section][_name] = _value;
	}
}

void AESettingsManager::saveSettings(void)
{
	Ogre::DataStreamPtr os = Ogre::Root::getSingleton().createFileStream(m_config_file,"User",true);

	string sec,key,value,line = "";

	Ogre::map<string,Ogre::NameValuePairList>::const_iterator iter;
	for(iter = m_config_options.begin(); iter != m_config_options.end(); iter++)
	{
		sec = iter->first;
		line = "["+sec+"]\n";
		os->write(line.c_str(),line.size());

		Ogre::NameValuePairList::const_iterator set;
		for(set = iter->second.begin(); set != iter->second.end(); set++)
		{
			key = set->first;
			value = set->second;
			line = key + "=" + value +"\n";
			os->write(line.c_str(),line.size());
		}
	}

	os->close();
}

END_ARETE_NAMESPACE